﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Xml;

namespace SDT.CrawlSystem.Tools
{
    /// <summary>
    /// Written by SinhNT
    /// </summary>
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

        #region In data
		private Dictionary<string, string> InData = new Dictionary<string, string>();
        private void btnIn_Click(object sender, EventArgs e)
        {
            if (openFileDlg.ShowDialog() == DialogResult.OK)
            {
                txtInFile.Text = openFileDlg.FileName;
                //clear key 
                InData = new Dictionary<string, string>();

                var r = new FileInfo(txtInFile.Text).OpenText();
                var l = r.ReadLine();
                var b = new StringBuilder();
                while (l != null)
                {
                    if (l.Trim().Length == 0)
                    {
                        l = r.ReadLine();
                        continue;
                    }

                    string[] items = l.Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries);
                    //Modify: It is greater than signal =
                    if (items.Length > 2)
                    {
                        for (int i = 2; i < items.Length; i++)
                            items[1] = items[1] + "=" + items[i];
                    }

                    #region Get params & update views
                    switch (items[0])
                    {
                        case "UrlFilterMin":
                            if (items.Length == 2)
                                UrlFilterMin = Convert.ToInt32(items[1]);
                            txtUrlFilterMin.Text = UrlFilterMin.ToString();
                            l = r.ReadLine();
                            continue;
                        case "UrlFilterStart":
                            if (items.Length == 2)
                                UrlFilterStart = items[1];
                            txtUrlFilterStart.Text = UrlFilterStart;
                            l = r.ReadLine();
                            continue;
                        case "UrlFilterEnd":
                            if (items.Length == 2)
                                UrlFilterEnd = items[1];
                            txtUrlFilterEnd.Text = UrlFilterEnd;
                            l = r.ReadLine();
                            continue;
                        case "UrlFilterContain":
                            if (items.Length == 2)
                                UrlFilterContain = items[1];
                            txtUrlFilterContain.Text = UrlFilterContain;
                            l = r.ReadLine();
                            continue;
                        case "WIDFilterStart":
                            if (items.Length == 2)
                                WIDFilterStart = items[1];
                            txtWIDFilterStart.Text = WIDFilterStart;
                            l = r.ReadLine();
                            continue;
                        case "WIDFilterEnd":
                            if (items.Length == 2)
                                WIDFilterEnd = items[1];
                            txtWIDFilterEnd.Text = WIDFilterEnd;
                            l = r.ReadLine();
                            continue;
                        case "WIDFilterRegEx":
                            if (items.Length == 2)
                                WIDFilterRegEx = items[1];
                            txtWIDFilterRegEx.Text = WIDFilterRegEx;
                            l = r.ReadLine();
                            continue;
                        case "GlobalPrefix":
                            if (items.Length == 2)
                                GlobalPrefix = items[1];
                            txtGlobalPrefix.Text = GlobalPrefix;
                            l = r.ReadLine();
                            continue;
                        case "GlobalFromId":
                            if (items.Length == 2)
                                GlobalFromId = Convert.ToInt32(items[1]);
                            txtGlobalFromId.Text = GlobalFromId.ToString();
                            l = r.ReadLine();
                            continue;
                        case "GlobalLoop":
                            if (items.Length == 2)
                                GlobalLoop = Convert.ToInt32(items[1]);
                            txtGlobalLoop.Text = GlobalLoop.ToString();
                            l = r.ReadLine();
                            continue;
                        default:
                            break;
                    }; 
                    #endregion
                  
                    InData.Add(items[0], items[1]);
                    l = r.ReadLine();
                    b.Append(l).Append("\r\n");
                }
                r.Close();

                txtInData.Text = b.ToString();
            }
        } 
	    #endregion     

        private void btnOut_Click(object sender, EventArgs e)
        {
            if (openFileDlg.ShowDialog() == DialogResult.OK)
            {
                txtOutFile.Text = openFileDlg.FileName;

                XmlWebBrowser.Navigate(txtOutFile.Text);
            }
        }

        #region Url Filter
        private int UrlFilterMin = 0;
        private void txtUrlFilterMin_TextChanged(object sender, EventArgs e)
        {
            try
            {
                UrlFilterMin = Convert.ToInt32(txtUrlFilterMin.Text.Trim());
            }
            catch { }
        }

        private string UrlFilterStart = string.Empty;
        private void txtUrlFilterStart_TextChanged(object sender, EventArgs e)
        {
            UrlFilterStart = txtUrlFilterStart.Text.Trim();
        }

        private string UrlFilterEnd = string.Empty;
        private void txtUrlFilterEnd_TextChanged(object sender, EventArgs e)
        {
            UrlFilterEnd = txtUrlFilterEnd.Text.Trim();
        }

        private string UrlFilterContain = string.Empty;
        private void txtUrlFilterContain_TextChanged(object sender, EventArgs e)
        {
            UrlFilterContain = txtUrlFilterContain.Text.Trim();
        } 
        #endregion

        #region WID Filter
        private string WIDFilterStart = "";
        private void txtWIDFilterStart_TextChanged(object sender, EventArgs e)
        {
            WIDFilterStart = txtWIDFilterStart.Text.Trim();
        }

        private string WIDFilterEnd = "";
        private void txtWIDFilterEnd_TextChanged(object sender, EventArgs e)
        {
            WIDFilterEnd = txtWIDFilterEnd.Text.Trim();
        }

        private string WIDFilterRegEx = "";
        private void txtWIDFilterRegEx_TextChanged(object sender, EventArgs e)
        {
            WIDFilterRegEx = txtWIDFilterRegEx.Text.Trim();
        } 
        #endregion

        #region Global params
        private string GlobalPrefix = "";
        private void txtGlobalPrefix_TextChanged(object sender, EventArgs e)
        {
            GlobalPrefix = txtGlobalPrefix.Text.Trim();
        }

        private int GlobalFromId = 0;
        private void txtGlobalFromId_TextChanged(object sender, EventArgs e)
        {
            try
            {
                GlobalFromId = Convert.ToInt32(txtGlobalFromId.Text.Trim());
            }
            catch { }
        }

        private int GlobalLoop = 0;
        private void txtGlobalLoop_TextChanged(object sender, EventArgs e)
        {
            try
            {
                GlobalLoop = Convert.ToInt32(txtGlobalLoop.Text.Trim());
            }
            catch { }
        }

        private string GlobalChannelName = "";
        private void txtChannelName_TextChanged(object sender, EventArgs e)
        {
            GlobalChannelName = txtChannelName.Text.Trim();
        }

        private int GlobalChannelId = 0;
        private void txtChannelId_TextChanged(object sender, EventArgs e)
        {
            try
            {
                GlobalChannelId = Convert.ToInt32(txtChannelId.Text.Trim());
            }
            catch { }
        }
        #endregion

        #region DB Connection
        private string DBCatalog = "";
        private void txtDBCatalog_TextChanged(object sender, EventArgs e)
        {
            DBCatalog = txtDBCatalog.Text.Trim();
        }

        private string DBUserId = "";
        private void txtDBUid_TextChanged(object sender, EventArgs e)
        {
            DBUserId = txtDBUid.Text.Trim();
        }

        private string DBPassword = "";
        private void txtDBPassword_TextChanged(object sender, EventArgs e)
        {
            DBPassword = txtDBPassword.Text.Trim();
        } 
        #endregion

        private static string Xml =
            @"<Channels>
                <LogFile>channel.log</LogFile>
	            <Interval>10000</Interval>
	            <WorkUnitInterval>2000</WorkUnitInterval>
                <Channel Id='' Active='' Name='' Update=''>
                    <Page Id='' Name='' Update=''>
                        <URLFilter MinLen='' StartWith='' EndWith='' Contain=''></URLFilter>
                        <WIDFilter StartWith='' EndWith='' RegEx=''></WIDFilter>
                        <Urls Prefix=''>
                            <Url Loop=''></Url>
                        </Urls>
                    </Page>
                </Channel>
            </Channels>";

        #region Control panel
        private void btnGenerate_Click(object sender, EventArgs e)
        {
            var d = new XmlDocument();
            d.LoadXml(Xml);
            var n = d.SelectSingleNode("Channels/Channel");

            n.Attributes["Id"].Value = GlobalChannelId.ToString();
            n.Attributes["Active"].Value = "0";
            n.Attributes["Update"].Value = "1";
            n.Attributes["Name"].Value = GlobalChannelName.Length == 0 ? GlobalPrefix : GlobalChannelName;

            n = n.SelectSingleNode("Page");

            var l = new List<XmlNode>();

            foreach (var i in InData.Keys)
            {
                l.Add(n);

                n.Attributes["Id"].Value = "0";
                n.Attributes["Name"].Value = i;
                n.Attributes["Update"].Value = "1";
                n.SelectSingleNode("URLFilter").Attributes["MinLen"].Value 
                    = UrlFilterMin == 0 ? UrlFilterContain.Length.ToString() : UrlFilterMin.ToString();
                n.SelectSingleNode("URLFilter").Attributes["StartWith"].Value = UrlFilterStart;
                n.SelectSingleNode("URLFilter").Attributes["EndWith"].Value = UrlFilterEnd;
                n.SelectSingleNode("URLFilter").Attributes["Contain"].Value
                    = InData[i].ToLower().Contains(@"/contain/")? GetURLFilter(InData[i]) : UrlFilterContain;

                n.SelectSingleNode("WIDFilter").Attributes["StartWith"].Value = WIDFilterStart;
                n.SelectSingleNode("WIDFilter").Attributes["EndWith"].Value = WIDFilterEnd;

                n.SelectSingleNode("WIDFilter").InnerText =string.Empty;
                n.SelectSingleNode("WIDFilter").AppendChild(d.CreateCDataSection(WIDFilterRegEx));
                n.SelectSingleNode("Urls").Attributes["Prefix"].Value = GlobalPrefix;

                n.SelectSingleNode("Urls/Url").Attributes["Loop"].Value = GlobalLoop.ToString();

                n.SelectSingleNode("Urls/Url").InnerText = string.Empty;
                //must be removed string &contain
                n.SelectSingleNode("Urls/Url").AppendChild(d.CreateCDataSection(
                    UrlClear(InData[i].Substring(GlobalPrefix.Length))));
           
                n = n.CloneNode(true);
            }

            n = d.SelectSingleNode("Channels/Channel");
            n.RemoveChild(n.FirstChild);
            foreach (var i in l)
            {
                n.AppendChild(i);
            }
            l.Clear();

            File.Delete("temp.xml");

            var wr = new XmlTextWriter("temp.xml", Encoding.UTF8);
            
            d.FirstChild.WriteTo(wr);
            wr.Close();
            txtOutFile.Text = Application.StartupPath + "\\temp.xml";
            XmlWebBrowser.Navigate(txtOutFile.Text);
        }
        #region URL Filter
        /// <summary>
        /// Ex: http://dantri.com.vn/c20s170/skphapluat/trang-1.htm&Contain=
        /// 
        /// </summary>
        /// <param name="pageurl"></param>
        /// <returns></returns>
        private string GetURLFilter(string pageurl)
        { 
            pageurl = pageurl.ToLower();
            pageurl = pageurl.Trim();
            int _startindex = pageurl.IndexOf("/contain/");
            return _startindex != -1 ? pageurl.Substring(_startindex + "/contain/".Length, pageurl.Length - _startindex - "/contain/".Length) : string.Empty;
            
        }

        private string UrlClear(string pageurl)
        {
            pageurl = pageurl.ToLower();
            pageurl = pageurl.Trim();
            int _startindex = pageurl.IndexOf("/contain/");

            return _startindex != -1 ? pageurl.Substring(0, _startindex).TrimEnd() : pageurl;
        }
        #endregion

        private void btnSaveToFile_Click(object sender, EventArgs e)
        {
            if (txtOutFile.Text.Length != 0 && File.Exists(txtOutFile.Text))
                if (saveFileDlg.ShowDialog() == DialogResult.OK)
                {
                    var saveTo = saveFileDlg.FileName;
                    TextReader r = new FileInfo(txtOutFile.Text).OpenText();
                    var content = r.ReadToEnd();
                    r.Close();

                    var b = new StringBuilder();

                    var pad = "  ";
                    var level = 0;

                    int i = 0;
                    while (i < content.Length)
                    {
                        var c = content[i];
                        while (c != '<' && i < content.Length)
                        {
                            i++;
                            continue;
                        }

                        var closeTag = content[i + 1] == '/';

                        level += closeTag ? -1 : 1;

                        for (int j = 0; j < level - 1; j++)
                            b.Append(pad);

                        if (closeTag)
                            b.Append(pad);

                        var idx = content.IndexOf('>', i);

                        b.Append(content.Substring(i, idx + 1 - i));
                        b.Append("\r\n");

                        i = idx + 1;

                        if (!closeTag)
                        {
                            // Find close tag
                            idx = content.IndexOf('<', i);
                            if (idx > i)
                            {
                                b.Remove(b.Length - 2, 2);
                                b.Append(content.Substring(i, idx - i));
                                b.Append("\r\n");
                                i = idx;
                            }
                        }
                    }

                    TextWriter w = new FileInfo(saveTo).CreateText();
                    w.Write(b.ToString());
                    w.Close();
                }
        }
        #endregion

        private void btnRevisionLog_Click(object sender, EventArgs e)
        {
            if (openFileDlg.ShowDialog() == DialogResult.OK)
            {
                txtInFile.Text = openFileDlg.FileName;
                var r = new FileInfo(txtInFile.Text).OpenText();
                var l = r.ReadLine();
                var bIn = new StringBuilder();
                var bOut = new StringBuilder();
                while (l != null)
                {
                    if (l.Trim().Length == 0)
                    {
                        l = r.ReadLine();
                        continue;
                    }
                    bIn.AppendLine(l);
                    var i = l.IndexOf("TIMEUP: ");
                    if (i > 0)
                        bOut.AppendLine(l.Substring(i + "TIMEUP: ".Length));

                    l = r.ReadLine();
                }
                r.Close();

                txtInData.Text = bIn.ToString();
                XmlWebBrowser.DocumentText = bOut.ToString();
            }
        }

        private void btnStatistics_Click(object sender, EventArgs e)
        {
            if (openFileDlg.ShowDialog() == DialogResult.OK)
            {
                txtInFile.Text = openFileDlg.FileName;
                var r = new FileInfo(txtInFile.Text).OpenText();
                var l = r.ReadLine();
                var bIn = new StringBuilder();
                var bOut = new StringBuilder();
                while (l != null)
                {
                    if (l.Trim().Length == 0)
                    {
                        l = r.ReadLine();
                        continue;
                    }
                    bIn.AppendLine(l);
                    var i = l.IndexOf("TOTAL=");
                    if (i >= 0)
                        bOut.AppendLine(l);

                    l = r.ReadLine();
                }
                r.Close();

                txtInData.Text = bIn.ToString();
                XmlWebBrowser.DocumentText = bOut.ToString();
            }
        }
    }
}